﻿using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using PlanningGIS.ArcGIS;
using PlanningGIS.Util.Convertor;

namespace PlanningGIS.MapSheet
{
    /// <summary>
    /// 
    /// </summary>
    public class SheetLayout : SheetFrame, IPageInfo
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sheet">图幅对象</param>
        /// <param name="scale">比例尺</param>
        public SheetLayout(Mapsheet sheet, int scale)
            : base(sheet, scale)
        {

        }

        #region IPageInfo

        /// <summary>
        /// 纸张类型
        /// </summary>
        private string _PageType = "A1";

        /// <summary>
        /// 获取或设置纸张类型A1~A6、B1~B5，与PageWidth、PageHeight二选一
        /// </summary>
        [Description("获取或设置纸张类型A1~A6、B1~B5，与PageWidth、PageHeight二选一【输入，可选】")]
        public string PageType
        {
            get { return _PageType; }
            set
            {
                _PageType = value.ToUpper();
                switch (_PageType)
                {
                    case "A2":
                        PageWidth = 59.4;
                        PageHeight = 42.0;
                        break;
                    case "A3":
                        PageWidth = 42.0;
                        PageHeight = 29.7;
                        break;
                    case "A4":
                        PageWidth = 29.7;
                        PageHeight = 21.0;
                        break;
                    case "A5":
                        PageWidth = 21.0;
                        PageHeight = 14.8;
                        break;
                    case "A6":
                        PageWidth = 14.8;
                        PageHeight = 10.5;
                        break;
                    case "B1":
                        PageWidth = 100.0;
                        PageHeight = 70.6;
                        break;
                    case "B2":
                        PageWidth = 70.6;
                        PageHeight = 50.0;
                        break;
                    case "B3":
                        PageWidth = 50.0;
                        PageHeight = 35.3;
                        break;
                    case "B4":
                        PageWidth = 35.3;
                        PageHeight = 25.0;
                        break;
                    case "B5":
                        PageWidth = 25.0;
                        PageHeight = 17.6;
                        break;
                    default:
                        PageWidth = 84.0;
                        PageHeight = 59.4;
                        break;
                }
            }
        }

        /// <summary>
        /// 获取或设置纸张的宽度，默认84.0
        /// </summary>
        [Description("获取或设置纸张的宽度，默认84.0【输入，可选】")]
        public double PageWidth { get; set; }

        /// <summary>
        /// 获取或设置纸张的高度，默认59.4
        /// </summary>
        [Description("获取或设置纸张的高度，默认59.4【输入，可选】")]
        public double PageHeight { get; set; }

        #endregion

        /// <summary>
        /// 布局绘制容器
        /// </summary>
        protected IGraphicsContainer _Graphics = null;

        /// <summary>
        /// 布局控件
        /// </summary>
        protected IPageLayoutControl3 _PageLayout = null;

        /// <summary>
        /// 默认颜色
        /// </summary>
        protected IRgbColor _DefaultColor = null;

        /// <summary>
        /// 在布局对象中绘制要打印的图幅信息
        /// </summary>
        /// <param name="pageLayout">布局对象</param>
        public void OnCreate(IPageLayoutControl3 pageLayout)
        {
            _PageLayout = pageLayout;
            _Graphics = (IGraphicsContainer)_PageLayout.PageLayout;
            Init();
            DeleteElement();
            DrawMap();
            DrawFrame();
            DrawCrosses();
            DrawSheets();
            DrawBottomMeta(InnerExtent.XMin, InnerExtent.YMin - _INNER_DIS - 0.3, BottomLeftValues);
            DrawBottomMeta(InnerExtent.XMax - 9, InnerExtent.YMin - _INNER_DIS - 0.3, BottomRightValues);
        }

        /// <summary>
        /// 初始化
        /// </summary>
        protected void Init()
        {
            IEnvelope env = Sheet.Geometry.Envelope;
            this.InnerExtent = new Envelope()
            {
                XMin = PageWidth / 2.0 - env.Width / Scale * 100 / 2.0,
                YMin = PageHeight / 2.0 - env.Height / Scale * 100 / 2.0,
                XMax = PageWidth / 2.0 + env.Width / Scale * 100 / 2.0,
                YMax = PageHeight / 2.0 + env.Height / Scale * 100 / 2.0
            } as IEnvelope;
            this.OuterExtent = new Envelope()
            {
                XMin = InnerExtent.XMin - _INNER_DIS,
                XMax = InnerExtent.XMax + _INNER_DIS,
                YMin = InnerExtent.YMin - _INNER_DIS,
                YMax = InnerExtent.YMax + _INNER_DIS
            } as IEnvelope;
            _DefaultColor = new RgbColor() { Red = 0, Green = 0, Blue = 0 };
            OffsetExtent = new ExpandoObject();
            OffsetExtent.XMin = Math.Round((env.XMin - XOffset) / UnitValue, 2);
            OffsetExtent.XMax = Math.Round((env.XMax - XOffset) / UnitValue, 2);
            OffsetExtent.YMin = Math.Round((env.YMin - YOffset) / UnitValue, 2);
            OffsetExtent.YMax = Math.Round((env.YMax - YOffset) / UnitValue, 2);
        }

        /// <summary>
        /// 绘制地图
        /// </summary>
        protected void DrawMap()
        {
            IMapFrame mapframe = null;
            IElement element = null;
            _Graphics.Reset();
            while ((element = _Graphics.Next()) != null)
            {
                if (element is IMapFrame)
                {
                    mapframe = element as IMapFrame;
                    break;
                }
            }
            _Graphics.Reset();
            ISymbolBorder symBorder = (ISymbolBorder)mapframe.Border;
            ILineSymbol lineSymbol = symBorder.LineSymbol;
            lineSymbol.Width = 0.1 * _TOPT_MM;
            symBorder.LineSymbol = lineSymbol;
            mapframe.Border = symBorder;
            IElement mapele = mapframe as IElement;
            mapele.Geometry = this.InnerExtent as IGeometry;
            mapframe.ExtentType = esriExtentTypeEnum.esriExtentBounds;
            mapframe.MapScale = Scale;
            mapframe.MapBounds = Sheet.Geometry.Envelope;
            (mapframe.Map as IActiveView).Refresh();
        }

        /// <summary>
        /// 绘制框架（图廓线、密级、图阔角点、标题）
        /// </summary>
        protected void DrawFrame()
        {
            //图廓线
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin - _INNER_DIS, InnerExtent.YMin, InnerExtent.XMax + _INNER_DIS, InnerExtent.YMin, _DefaultColor, 0.1 * _TOPT_MM), 8); //下
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin - _INNER_DIS, InnerExtent.YMax, InnerExtent.XMax + _INNER_DIS, InnerExtent.YMax, _DefaultColor, 0.1 * _TOPT_MM), 8); //上
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin, InnerExtent.YMin - _INNER_DIS, InnerExtent.XMin, InnerExtent.YMax + _INNER_DIS, _DefaultColor, 0.1 * _TOPT_MM), 8); //左
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMax, InnerExtent.YMin - _INNER_DIS, InnerExtent.XMax, InnerExtent.YMax + _INNER_DIS, _DefaultColor, 0.1 * _TOPT_MM), 8); //右

            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin - _INNER_DIS, InnerExtent.YMin - _INNER_DIS, InnerExtent.XMin - _INNER_DIS, InnerExtent.YMax + _INNER_DIS, _DefaultColor, 1 * _TOPT_MM), 8); //下
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin - _INNER_DIS, InnerExtent.YMax + _INNER_DIS, InnerExtent.XMax + _INNER_DIS, InnerExtent.YMax + _INNER_DIS, _DefaultColor, 1 * _TOPT_MM), 8); //上
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMax + _INNER_DIS, InnerExtent.YMax + _INNER_DIS, InnerExtent.XMax + _INNER_DIS, InnerExtent.YMin - _INNER_DIS, _DefaultColor, 1 * _TOPT_MM), 8); //左
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMax + _INNER_DIS, InnerExtent.YMin - _INNER_DIS, InnerExtent.XMin - _INNER_DIS, InnerExtent.YMin - _INNER_DIS, _DefaultColor, 1 * _TOPT_MM), 8); //右

            //密级
            if (!string.IsNullOrWhiteSpace(SecurityLevel))
                _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMax, InnerExtent.YMax + _INNER_DIS + 0.5, SecurityLevel, (decimal)(4 * _TOPT_MM), esriTextHorizontalAlignment.esriTHARight, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            //图阔角点
            decimal fontsize = (decimal)(3 * _TOPT_MM);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin, InnerExtent.YMin - _INNER_DIS + 0.15, ObjectConvertor.ToString(((double)OffsetExtent.XMin), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin - _INNER_DIS + 0.15, InnerExtent.YMin + 0.15, ObjectConvertor.ToString(((double)OffsetExtent.YMin), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHALeft, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin, InnerExtent.YMax + _INNER_DIS - 0.15, ObjectConvertor.ToString(((double)OffsetExtent.XMin), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVATop, "宋体", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin - _INNER_DIS + 0.15, InnerExtent.YMax + 0.15, ObjectConvertor.ToString(((double)OffsetExtent.YMax), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHALeft, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMax, InnerExtent.YMax + _INNER_DIS - 0.15, ObjectConvertor.ToString(((double)OffsetExtent.XMax), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVATop, "黑体", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMax + _INNER_DIS - 0.15, InnerExtent.YMax + 0.15, ObjectConvertor.ToString(((double)OffsetExtent.YMax), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHARight, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMax, InnerExtent.YMin - _INNER_DIS + 0.15, ObjectConvertor.ToString(((double)OffsetExtent.XMax), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMax + _INNER_DIS - 0.15, InnerExtent.YMin + 0.15, ObjectConvertor.ToString(((double)OffsetExtent.YMin), 2).ToString(), fontsize, esriTextHorizontalAlignment.esriTHARight, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            //标题
            _Graphics.AddElement(ElementHelper.CreateText(PageWidth / 2.0, InnerExtent.YMax + _INNER_DIS + 0.5, Sheet.Code, (decimal)(5 * _TOPT_MM), esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            if (!string.IsNullOrEmpty(SheetName) || !string.IsNullOrWhiteSpace(SheetName))
                _Graphics.AddElement(ElementHelper.CreateText(PageWidth / 2.0, InnerExtent.YMax + _INNER_DIS + 1.3, SheetName, (decimal)(6 * _TOPT_MM), esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            //比例尺
            _Graphics.AddElement(ElementHelper.CreateText(PageWidth / 2.0, InnerExtent.YMin - _INNER_DIS + 0.5, "1:" + Scale.ToString(), (decimal)(4 * _TOPT_MM), esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVABaseline, "宋体", false, 0), 9);
            //单位名称
            if (!string.IsNullOrWhiteSpace(UnitName))
            {
                fontsize = (decimal)(4 * _TOPT_MM);
                string strUnit = StringHelper.TextH2V(UnitName);
                _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin - _INNER_DIS - 0.4, InnerExtent.YMin, strUnit, fontsize, esriTextHorizontalAlignment.esriTHARight, esriTextVerticalAlignment.esriTVABottom, "宋体", false, 0), 9);
            }
        }

        /// <summary>
        /// 绘制横向、纵向网线十字叉及短线
        /// </summary>
        protected void DrawCrosses()
        {
            int iCrossW = (Convert.ToInt32(InnerExtent.Width / 10)) - 1;
            int iCrossH = (Convert.ToInt32(InnerExtent.Height / 10)) - 1;
            //生成网线十字叉
            for (int i = 1; i <= iCrossW; i++)
            {
                double x0 = InnerExtent.XMin + i * 10;
                for (int j = 1; j <= iCrossH; j++)
                {
                    double y0 = InnerExtent.YMin + j * 10;
                    _Graphics.AddElement(ElementHelper.CreateLine(x0 - 0.5, y0, x0 + 0.5, y0, _DefaultColor, 0.1 * _TOPT_MM), 0);
                    _Graphics.AddElement(ElementHelper.CreateLine(x0, y0 - 0.5, x0, y0 + 0.5, _DefaultColor, 0.1 * _TOPT_MM), 0);
                }
            }

            //生成坐标网线短线
            for (int i = 1; i <= iCrossH; i++)
            {
                double y0 = InnerExtent.YMin + i * 10;
                _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin, y0, InnerExtent.XMin + 0.5, y0, _DefaultColor, 0.1 * _TOPT_MM), 0);
                _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMax - 0.5, y0, InnerExtent.XMax, y0, _DefaultColor, 0.1 * _TOPT_MM), 0);
            }

            for (int i = 1; i <= iCrossW; i++)
            {
                double x0 = InnerExtent.XMin + i * 10;
                _Graphics.AddElement(ElementHelper.CreateLine(x0, InnerExtent.YMin, x0, InnerExtent.YMin + 0.5, _DefaultColor, 0.1 * _TOPT_MM), 0);
                _Graphics.AddElement(ElementHelper.CreateLine(x0, InnerExtent.YMax, x0, InnerExtent.YMax - 0.5, _DefaultColor, 0.1 * _TOPT_MM), 0);
            }
        }

        /// <summary>
        /// 绘制左上角图幅标识（九宫格）
        /// </summary>
        protected void DrawSheets()
        {
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin, InnerExtent.YMax + 0.3 + _INNER_DIS, InnerExtent.XMin, InnerExtent.YMax + 0.3 + 2.4 + _INNER_DIS, _DefaultColor, 0.1 * _TOPT_MM), 0);
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin, InnerExtent.YMax + 0.3 + 2.4 + _INNER_DIS, InnerExtent.XMin + 4.5, InnerExtent.YMax + 0.3 + 2.4 + _INNER_DIS, _DefaultColor, 0.1 * _TOPT_MM), 0);
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin + 4.5, InnerExtent.YMax + 0.3 + 2.4 + _INNER_DIS, InnerExtent.XMin + 4.5, InnerExtent.YMax + 0.3 + _INNER_DIS, _DefaultColor, 0.1 * _TOPT_MM), 0);
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin + 4.5, InnerExtent.YMax + 0.3 + _INNER_DIS, InnerExtent.XMin, InnerExtent.YMax + 0.3 + _INNER_DIS, _DefaultColor, 0.1 * _TOPT_MM), 0);

            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin, InnerExtent.YMax + 0.3 + _INNER_DIS + 0.8, InnerExtent.XMin + 4.5, InnerExtent.YMax + 0.3 + _INNER_DIS + 0.8, _DefaultColor, 0.1 * _TOPT_MM), 9);
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin, InnerExtent.YMax + 0.3 + _INNER_DIS + 1.6, InnerExtent.XMin + 4.5, InnerExtent.YMax + 0.3 + _INNER_DIS + 1.6, _DefaultColor, 0.1 * _TOPT_MM), 9);
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin + 1.5, InnerExtent.YMax + 0.3 + _INNER_DIS, InnerExtent.XMin + 1.5, InnerExtent.YMax + 0.3 + _INNER_DIS + 2.4, _DefaultColor, 0.1 * _TOPT_MM), 9);
            _Graphics.AddElement(ElementHelper.CreateLine(InnerExtent.XMin + 3.0, InnerExtent.YMax + 0.3 + _INNER_DIS, InnerExtent.XMin + 3.0, InnerExtent.YMax + 0.3 + _INNER_DIS + 2.4, _DefaultColor, 0.1 * _TOPT_MM), 9);

            if (SheetCodes == null || SheetCodes.Count == 0) return;
            decimal fontsize = (decimal)(2.5 * _TOPT_MM);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 0.75, InnerExtent.YMax + _INNER_DIS + 0.3 + 2, SheetCodes[0], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 2.25, InnerExtent.YMax + _INNER_DIS + 0.3 + 2, SheetCodes[1], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 3.75, InnerExtent.YMax + _INNER_DIS + 0.3 + 2, SheetCodes[2], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);

            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 0.75, InnerExtent.YMax + _INNER_DIS + 0.3 + 1.2, SheetCodes[3], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);
            //ElementHelper.AddText(XMin + 2.25, YMax + _INNER_DIS + 0.3 + 1.2, SheetCodes[4], (decimal)(2.5 * _TOPT_MM), esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 3.75, InnerExtent.YMax + _INNER_DIS + 0.3 + 1.2, SheetCodes[4], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);

            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 0.75, InnerExtent.YMax + _INNER_DIS + 0.3 + 0.4, SheetCodes[5], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 2.25, InnerExtent.YMax + _INNER_DIS + 0.3 + 0.4, SheetCodes[6], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);
            _Graphics.AddElement(ElementHelper.CreateText(InnerExtent.XMin + 3.75, InnerExtent.YMax + _INNER_DIS + 0.3 + 0.4, SheetCodes[7], fontsize, esriTextHorizontalAlignment.esriTHACenter, esriTextVerticalAlignment.esriTVACenter, "华文细黑", false, 0), 9);

        }

        /// <summary>
        /// 绘制底部的元数据信息
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="values"></param>
        protected void DrawBottomMeta(double x, double y, List<string> values)
        {
            if (values == null || values.Count == 0) return;
            decimal fontsize = (decimal)(3 * _TOPT_MM);
            foreach (string value in values)
            {
                IElement ele = ElementHelper.CreateText(x, y, value, fontsize, esriTextHorizontalAlignment.esriTHALeft, esriTextVerticalAlignment.esriTVATop, "华文细黑", false, 0);
                _Graphics.AddElement(ele, 9);
                double txtw = 0;
                double txth = 0;
                (ele as ITextElement).Symbol.GetTextSize(_PageLayout.ActiveView.ScreenDisplay.get_CacheMemDC(0), _PageLayout.ActiveView.ScreenDisplay.DisplayTransformation, value, out txtw, out txth);
                y -= (0.2 + (txth / 72 * 2.54));
            }
        }

        /// <summary>
        /// 删除绘制的Element对象
        /// </summary>
        protected void DeleteElement()
        {
            if (_Graphics == null) return;
            _Graphics.Reset();
            IElement oldele = null;
            List<IElement> oldels = new List<IElement>();
            while ((oldele = _Graphics.Next()) != null)
            {
                if (!(oldele is IMapFrame)) oldels.Add(oldele);
            }
            _Graphics.Reset();
            foreach (IElement ele in oldels)
            {
                _Graphics.DeleteElement(ele);
            }
        }

    }
}
